#encoding:utf-8 

import json, os, shutil, logging, sys, string, time
from optparse import OptionParser
from _helpscript import template_VER_LUA
from _helpscript import template_RELEASE_LUA

import plistlib
from ReleaseZiplua import ScriptPack
import re

reload(sys)
sys.setdefaultencoding('utf8')

# linux windows文件路径兼容
def path_compatible(path):
    return string.replace(path, "/", os.sep)

#kill 进程
def kill_process():
    os.system("killall Finder")
    os.system("killall Xcode")

# 获取签名文件的uuid
def get_profile_uuid(profile):
    logging.info ("Check the file if provision file -->>>%s", profile)
    ret = os.popen('''/usr/libexec/PlistBuddy -c "Print UUID" /dev/stdin <<< $(/usr/bin/security cms -D -i %s)'''%profile).readlines()
    return ret[0].strip()

# 添加文本log记录
def add_filelogger(toolpath):
    rlogger = logging.getLogger() 
    filehandler = logging.FileHandler(toolpath + "/BuildRelease/iospack.log", mode="w+", encoding='utf-8')
    fileformater= logging.Formatter('%(asctime)s - %(name)s - %(levelname)s ---> %(message)s')
    filehandler.setFormatter(fileformater) 
    rlogger.addHandler(filehandler)

# 参数初始化-->>play800
def _init_play800_parms(cls, pcfg): 
    cls._aid = pcfg["aid"]
    cls._datakey = pcfg["datakey"]
    cls._datasite = pcfg["datasite"]
    cls._paykey = pcfg["paykey"]
    cls._paysite = pcfg["paysite"]
    cls._reyunkey = pcfg["reyunkey"]


# plist初始化-->>play800
def _handle_play800_parms(cls, plistfile, iosdir):
    logging.info("Copy the files to template path for pack...")
    plistfile = path_compatible(iosdir + "/ios/Info.plist")
    infodic = plistlib.readPlist(plistfile)

    infodic["CFBundleShortVersionString"] = cls._binver
    infodic["CFBundleDisplayName"] = cls._appname
    infodic["Game aid"] = cls._aid 
    infodic["Game datakey"] = cls._datakey
    infodic["Game datasite"] = cls._datasite
    infodic["Game paykey"] = cls._paykey
    infodic["Game paysite"] = cls._paysite
    infodic["Game reyunkey"] = cls._reyunkey
    infodic["game_bigver"] = cls._cliver
    infodic["CFBundleURLTypes"][0]["CFBundleURLName"] = cls._bundlename
    infodic["CFBundleURLTypes"][0]["CFBundleURLSchemes"] = [string.split(cls._packagename, ".")[0]]
    logging.info("Set the info.plist file params-->>\n")
    logging.info(infodic)
    plistlib.writePlist(infodic, plistfile)

class IOSPack:
    
    global _init_play800_parms
    global _init_i4_parms 
    global _init_zongsi_parms
    global _init_shenhai_parms

    global _handle_play800_parms
    global _handle_i4_parms
    global _handle_zongsi_parms
    global _handle_shenhai_parms


    PLAT_INITPARMS_MAP = {
        "play800":_init_play800_parms
    }

    PLAT_HANDLEPARMS_MAP = {
        "play800":_handle_play800_parms
    }


    '''初始化json打包的参数'''
    @classmethod
    def _initConfig(cls, jsonfile):
        try:
            f = open(jsonfile, "r+")
            pcfg = json.loads(f.read().decode('utf-8'))
            logging.info("Read the pack config...")
            logging.info(json.dumps(pcfg, sort_keys=True, indent=4))
            f.close()
        except Exception as e:
            logging.info(e)
            logging.error("Read file <%s> faild!", jsonfile)
            sys.exit()

        try:
            cls._mode = pcfg["mode"] 
            cls._platform = pcfg["platform"]
            cls._resver = pcfg["resver"]
            cls._binver = pcfg["binver"]
            cls._appname = pcfg["appname"]
            cls._iconpath = pcfg["iconpath"]
            cls._pagepath = pcfg["pagepath"]
            cls._packagename = pcfg["packagename"]
            cls._bundlename = pcfg["bundlename"]
            cls._profilelist = pcfg["profilelist"]
            cls._upkg_path = pcfg["upkg_path"]

            #script config
            cls._feidou_f = pcfg["feidou_f"]
            cls._feidou_gameid = pcfg["feidou_gameid"]
            cls._channel_id = pcfg["channel_id"]
            cls._cliver = pcfg["cliver"]
            cls._os = pcfg["os"]
            cls._lang = pcfg["language"]

            cls.DEBUG_LEVEL = 0

            #init by platform 
            cls.PLAT_INITPARMS_MAP[cls._platform](cls, pcfg)
            logging.info("Done!\n")
        except Exception as e:
            logging.error("Not find the need value in json file!")
            logging.info(e)
            sys.exit()

    
    '''初始化打包的临时路径'''
    @classmethod
    def _initTmpdir(cls):
        tmpdir = os.path.join(cls._basepath, "TEMPLATE_IOS_PACK")
        if os.path.isdir(tmpdir):
            shutil.rmtree(tmpdir)
        os.mkdir(tmpdir)
        return tmpdir


    #自动加入签名和证书
    @classmethod
    def auto_add_p12_provision(cls,tools_path):

        p12_list = cls._profilelist["p12"]
        cmd_str = "security unlock-keychain -p 123 /Users/kaixin/Library/Keychains/login.keychain"
        os.system(cmd_str)

        password = ""

        if "password" in cls._profilelist:
            password = cls._profilelist["password"]

        print("password =="+password)

        _keytool = "keytool"

        codesign_list = []
        for filename in p12_list:
            try:
                cmd_str = "security import {p12_file_path} -k /Users/kaixin/Library/Keychains/login.keychain -P '{password}' -T /usr/bin/codesign" 
                cmd_str = cmd_str.format(p12_file_path = tools_path + os.sep + "BuildRelease" + os.sep + filename, password = password)
                print("cmd_str ="+cmd_str)   
                os.system(cmd_str)
                if filename.find("ios_") >0:
                    print("cmd_str ="+"{keytool} -list -keystore {p12_file_path} -storepass '{password}' -storetype pkcs12 -v".format(keytool = _keytool, p12_file_path = tools_path + os.sep + "BuildRelease" + os.sep + filename, password = password))
                    ret = os.popen("{keytool} -list -keystore {p12_file_path} -storepass '{password}' -storetype pkcs12 -v".format(keytool = _keytool, p12_file_path = tools_path + os.sep + "BuildRelease" + os.sep + filename, password = password))
                    data = ret.read()
                    ret.close()
                    temp_codesign_list = re.findall(r"iPhone \w+: .+ [(]\w+[)]",data)

                    if len(temp_codesign_list) > 0 :
                        codesign_list.append(temp_codesign_list[0])
                    else:
                        sys.exit()
            except Exception as e:
                logging.error("error:%s"%e)
                sys.exit()

        provision_list = cls._profilelist["provision"]
        plist_dict = dict()

        for filename in provision_list:
            logging.info(u"provisionfile -->\n %s " % (tools_path + os.sep + "BuildRelease" + filename))
            cmd_str = "security cms -D -i {provisionfile}"
            ret = os.popen(cmd_str.format(provisionfile = tools_path + os.sep + "BuildRelease" + filename))
            data = ret.read()
            ret.close()
            infodic = plistlib.readPlistFromString(data)

            logging.info(infodic["TeamIdentifier"])

            _dict = dict()
            _dict["TeamName"] = infodic["TeamName"]
            _dict["TeamIdentifier"] = infodic["TeamIdentifier"][0]
            _dict["UUID"] = infodic["UUID"]
            _dict["filename"] = filename

            for key in codesign_list:
                if filename.find("_dev") > 0 :
                    if key.find("Dev") > 0:
                        _dict["codesign"] = key
                else:
                    if key.find("Dis") > 0:
                        _dict["codesign"] = key
            
            if filename.find("_dev") > 0 :
                plist_dict["dev"] = _dict
            else:
                plist_dict["dis"] = _dict
        
            logging.info("<--------------- setup this ------------->")
            logging.info("uuid:"+infodic["UUID"])
            provision_file_path = tools_path + os.sep + "BuildRelease" + os.sep + filename
            provision_copy_file_path = path_compatible("/Users/kaixin/Library/MobileDevice/Provisioning Profiles/" + infodic["UUID"] + ".mobileprovision")
            shutil.copy(provision_file_path, provision_copy_file_path)

        logging.info("plist_dict ------>",plist_dict)
        return plist_dict


    @classmethod 
    def _handleios(cls, iosdir, projefile, tarname, isclean, prouuid, codesign, tarfile):        
        cmd_str = "cd {iosdir} && xcodebuild -project {project} -target {tarname}-mobile -configuration Release \
                                                                                         ONLY_ACTIVE_ARCH=NO \
                                                                                         CONFIGURATION_BUILD_DIR={tardir} \
                                                                                         CODE_SIGN_IDENTITY='{codesign}'  \
                                                                                         PROVISIONING_PROFILE='{prouuid}' "\
                                                                                         .format(project=projefile, iosdir=iosdir, tarname=tarname, tardir=path_compatible(iosdir+"/build/Release-iphones"), codesign=codesign, prouuid=prouuid)

        logging.info("Execute then xcodebuild build command ->\n %s"%cmd_str)                               
        ret = os.system(cmd_str)

        cmd_str = "xcrun -sdk iphoneos packageApplication -v {appfile} -o {tarfile}".format(appfile=path_compatible(iosdir + ("/build/Release-iphones/"+tarname+".app")), tarfile=tarfile, codesign = codesign)
        logging.info("Execute then xcrun command ->\n %s"%cmd_str)
        ret = os.system(cmd_str)
        return tarfile
        
    '''打包执行'''  
    @classmethod
    def excute(cls, basepath, toolpath, jsonfile, isclean):
        #add logger
        add_filelogger(toolpath)
        cls._basepath = basepath        
        basedir = basepath
       
        #add import 
        pylibs = path_compatible(toolpath + "/BuildRelease")
        from pylibs import LuaPackHot

        #拷贝文件夹下内容
        def copy_(frompath_, tarpath_, ignorefile=""):
            for item in os.listdir(frompath_):
                itemobj = os.path.join(frompath_, item)
                if os.path.isfile(itemobj):
                    if item != ignorefile: 
                        shutil.copy(itemobj, tarpath_)
                    else:
                        logging.info("Copy ignore the file  -->>%s!"%ignorefile)
                elif os.path.isdir(itemobj):
                    tardir = os.path.join(tarpath_, item)
                    if not os.path.isdir(tardir):
                        os.mkdir(tardir)
                    copy_(itemobj, tardir)
        
        #==================================================================
        #init
        logging.info("Init the json-config...")
        jsonconfig = path_compatible(toolpath + "/BuildRelease/config/" + jsonfile)
        cls._initConfig(jsonconfig) 

        logging.info("copy sdks...")
        copy_(os.path.join(basedir, "sdks/ios"), path_compatible(toolpath + "/BuildRelease/"))

        #======================= Step ready-打包upkg =======================

        #游戏内的script单独处理 从res里面打包生成
        _res_path = os.path.join(basedir, "res")
        logging.info("res_path ="+_res_path)
        logging.info("cls._platform ="+cls._platform)
        ScriptPack.excute(_res_path, os.path.join(basedir, "proj.ios_mac_%s"%cls._platform) + "/lpkg", toolpath, cls,"jitmix")

        #======================= Step ready-导入证书 =======================

        cls.code_sign_info_list = cls.auto_add_p12_provision(toolpath)

        
        #======================= Step 1-创建临时工程 =======================
        iosdir = cls._initTmpdir()
        logging.info("Copy file from {fromdir} to {target}".format(fromdir=os.path.join(basedir, "proj.ios_mac_%s"%cls._platform), target=iosdir))
        copy_(os.path.join(basedir, "proj.ios_mac_%s"%cls._platform), iosdir)

        #======================= Step 2-格式化 plist file =======================
        '''====================================================================='''

        cls.PLAT_HANDLEPARMS_MAP[cls._platform](cls, cls._platform, iosdir)

        logging.info("Copy the files to template path for pack...")

        #格式化GameConfig.xml
        # gcfgxml = path_compatible(toolpath + "/BuildRelease/template/GameConfig.xml")
        # fobj = open(gcfgxml, "r")
        # fret = fobj.read().decode('utf-8')

        # fobjret1 = fret.replace("@VERSION_STR@", cls._binver).replace("@BUNDLENAME@", cls._bundlename).replace("@SERVER_PATH@", cls.SERVER_PATH)
        # fobj.close()
        # fobj2 = open(os.path.join(iosdir, "GameConfig.xml"), "w+")
        # fobj2.write(fobjret1.encode("utf-8"))
        # fobj2.close()

        #====================== Step 3-处理图标 =======================
        '''====================================================================='''
        tmpicon = path_compatible(iosdir + "/hjzzsix-mobile/Images.xcassets/AppIcon.appiconset")

        taricon = path_compatible(toolpath + "/BuildRelease/iconpath/%s/1024.png"%cls._iconpath)
        if os.path.isfile(taricon) == False:
            logging.error("Chk the icon is exit!-->>%s", taricon)
            sys.exit()
        logging.info("Auto create icons....")
        LuaPackHot.pack_icon(taricon, tmpicon, "ios")

        tmppage = path_compatible(iosdir + "/ios")
        tarpage = path_compatible(toolpath + "/BuildRelease/pagepath/%s/default.png"%cls._pagepath)
        if os.path.isfile(tarpage) == False:
            logging.error("Chk the page is exit!-->>%s", tarpage)
            sys.exit()
        logging.info("Auto create page....")
        LuaPackHot.pack_page(tarpage,tmppage,"ios")

        logging.info("Auto create game page....")
        targamepage = path_compatible(basedir + "/res_pvr/map/" + "init_bg.jpg")
        LuaPackHot.pack_game_pack(tarpage,targamepage,"ios")

        #======================= Step 4-修改工程.pbxproj =======================
        BASE_NAME = "hjzzsix"
        TAR_NAME = string.split(cls._packagename, ".")[0]
        BASE_PACKAGE = "com.hjzz.six"
        xcodeproj = path_compatible(iosdir+"/%s.xcodeproj"%BASE_NAME)
        xcodeproj2 = path_compatible(iosdir+"/%s.xcodeproj"%TAR_NAME)
        os.renames(path_compatible(iosdir + "/hjzzsix-mobile/"), path_compatible(iosdir + "/{tarname}-mobile/".format(tarname = TAR_NAME)))

        logging.info("Creat the target's xcodeproj file->%s..."%xcodeproj2)
        rfile = open(os.path.join(xcodeproj, "project.pbxproj"), "r")
        xcontent = rfile.read() 

        print("BASE_NAME ="+BASE_NAME)
        print("TAR_NAME ="+TAR_NAME)
        print("BASE_PACKAGE ="+BASE_PACKAGE)
        print("cls._bundlename ="+cls._bundlename)

        xcontent = xcontent.replace(BASE_NAME,TAR_NAME).replace(BASE_PACKAGE, cls._bundlename)
        rfile.close() 
        
        shutil.rmtree(xcodeproj)
        os.mkdir(xcodeproj2)

        wfile = open(os.path.join(xcodeproj2, "project.pbxproj"), "w")
        wfile.write(xcontent)
        wfile.close()

        #=======================  Step-5 执行打包 ======================= 

        logging.info("pack ipa ---------------------------->")

        cmd_str = "cd {iosdir} && xcodebuild -target {tarname}-mobile clean".format(iosdir=iosdir, tarname=TAR_NAME)
        logging.info("Execute then xcodebuild clean command ->\n %s"%cmd_str)
        ret = os.system(cmd_str)

        for _info in cls.code_sign_info_list:
            prouuid = cls.code_sign_info_list[_info]["UUID"]
            logging.info("prouuid ="+prouuid)
            profilename = cls.code_sign_info_list[_info]["filename"].split('/')[-1].split(".")[0]
            newname = "{platform}_{tarname}_{time}_{mode}_{version}.ipa".format(time=time.strftime("%m%d%H%M", time.localtime()), platform=cls._platform, mode="release", tarname=profilename,version=cls._binver)
            code_sign = cls.code_sign_info_list[_info]["codesign"]
            logging.info("code_sign ="+code_sign)

            isclean = False

            tar_file = cls._handleios(iosdir, xcodeproj2, TAR_NAME, isclean, prouuid,code_sign , os.path.join(basedir, newname))
            logging.info("Builde the ipa file finish!")
            os.system("sh "+toolpath + "/BuildRelease/sendToFTP.sh " + tar_file)
 
        os.system("say finish the ipa pack!")
        
    '''ipa信息查看'''
    @classmethod
    def chkipa(cls, ipafile):
        basedir = cls._basepath
        cmd_str = "security cms -D -i %s"%ipafile
        tmpfile = os.path.join(basedir, "TEMPLATE_IPA.zip")
        shutil.copy(ipafile, tmpfile)

        zippath = path_compatible(basedir + "/Payload")
        if os.path.isdir(zippath):
            shutil.rmtree(zippath)
        os.system("unzip %s"%tmpfile)
        appfile = os.listdir(zippath)[0]
        infofile = path_compatible(zippath + "/%s/embedded.mobileprovision"%appfile)
        ret = os.popen("security cms -D -i %s"%infofile).read()
        logging.info(ret)

        shutil.rmtree(zippath)
        os.remove(tmpfile)

if __name__ == "__main__":
    print("======================================")
    print("===============IOSPack================")
    print("======================================")

    parser = OptionParser()
    #type1 pack the ipa
    parser.add_option("-t", "--toolpath", dest="toolpath", help="Input the tools path!")
    parser.add_option("-f", "--jsonfile", dest="jsonfile", help="Input the json config file for pack the apk!")
    parser.add_option("-p", "--projpath", dest="projpath", help="Project base path")
    parser.add_option("-c", "--clean", dest="isclean", help="If clean the project")
    
    # #type2 chk the ipa
    parser.add_option("-i", "--ipafile", dest="ipafile", help="Chk the ipa file")

    (opts, args) = parser.parse_args()
    if (opts.jsonfile):
        kill_process()
        bdic = dict(
            true=True,
            false=False
        )
        jsonlist = opts.jsonfile.split(",") 
        if len(jsonlist) > 1:
            for jsonobj in jsonlist:
                IOSPack.excute(opts.projpath, opts.toolpath, jsonobj, bdic[opts.isclean])
        else:
            IOSPack.excute(opts.projpath, opts.toolpath, jsonlist[0], bdic[opts.isclean])
    elif (opts.ipafile):
        IOSPack.chkipa(opts.ipafile)
